package com.xin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xin.constants.ShopConstants;
import com.xin.entity.common.Point;
import com.xin.entity.common.TextAuditEntity;
import com.xin.entity.crm.EmployEntity;
import com.xin.entity.shop.ShopEmployeeEntity;
import com.xin.entity.shop.ShopEntity;
import com.xin.entity.shop.ShopOperateLogEntity;
import com.xin.entity.shop.dto.ShopRegisterDto;
import com.xin.exception.MyException;
import com.xin.mapper.EmployeeMapper;
import com.xin.mapper.ShopMapper;
import com.xin.service.EmployeeService;
import com.xin.service.ShopEmployeeService;
import com.xin.service.ShopOperateLogService;
import com.xin.service.ShopService;
import com.xin.utils.BaiduAuditUtil;
import com.xin.utils.DistanceUtil;
import com.xin.utils.EmailUtils;
import com.xin.utils.FastdfsUtil;
import com.xin.utils.FileUtils;
import com.xin.utils.HtmUtils;
import com.xin.utils.StringUtils;
import com.xin.utils.TextCensor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.security.provider.SHA;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 商户
 */
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, ShopEntity> implements ShopService {

    @Value("${file.fileUrl}")
    private String serverUrl;
    @Resource
    private JavaMailSender javaMailSender;
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 注入员工业务类
     */
    @Resource
    private EmployeeService employeeService;

    @Resource
    private EmployeeMapper employeeMapper;

    /**
     * 注入员工和店铺中间表业务类
     */
    @Resource
    private ShopEmployeeService shopEmployeeService;

    @Lazy
    @Resource
    private ShopOperateLogService shopOperateLogService;
    /**
     * 商家入驻
     * @param shopRegisterDto
     * @return
     */
    @Override
    @Transactional
    public Integer settleIn(ShopRegisterDto shopRegisterDto) {
        //说明用户是修改操作
        if (shopRegisterDto.getShop().getId()!=null) return this.updateShopMaterial(shopRegisterDto);
        EmployEntity entity = new EmployEntity();
        //获取前端传递过来的管理员信息
        entity.setUsername(shopRegisterDto.getUsername());
        entity.setPassword(shopRegisterDto.getPassword());
        entity.setPhone(shopRegisterDto.getPhone());
        entity.setEmail(shopRegisterDto.getEmail());
        //获取店铺信息
        //获取店铺信息
        ShopEntity shop = shopRegisterDto.getShop();

        //是否是修改店铺信息
        //调用三分接口自动审核
        autoAudit(shop);
        //设置店铺log
        String filePath = StringUtils.getFilePath(shop.getLogo(), serverUrl);
        shop.setLogo(filePath);

        //设置当前店铺的状态
        shop.setState(ShopEntity.AUDIT);
        //获取店铺的经纬度
        Point point = DistanceUtil.getPoint(shop.getAddress());
        //设置店铺的经纬度
        shop.setLongitude(point.getLat());
        shop.setDimension(point.getLng());


        //查看员工共账号名是否重复
        EmployEntity employEntity = this.employeeMapper.selectOne(new QueryWrapper<EmployEntity>().eq("username", entity.getUsername()));
        if (employEntity!=null) throw new MyException("账号名已存在");
        //保存当前员工数据
        this.employeeService.save(entity);
        //保存当前店铺信息
        this.save(shop);
        //创建店铺和员工之间的联系
        ShopEmployeeEntity shopEmployeeEntity = new ShopEmployeeEntity();
        shopEmployeeEntity.setEmployeeId(entity.getId());
        shopEmployeeEntity.setIsAdmin(1);
        shopEmployeeEntity.setShopId(shop.getId());
        //写入中间表，关联员工和店铺
        this.shopEmployeeService.save(shopEmployeeEntity);

        return 1;
    }

    /**
     * 显示所有商家信息
     * @param page
     * @param size
     * @return
     */
    @Override
    public Page<ShopEntity> findAll(Integer page, Integer size) {
        Page<ShopEntity> pages  = new Page<>(page,size);
        Page<ShopEntity> shopEntityPage = this.baseMapper.selectPage(pages, null);
        return shopEntityPage;
    }

    /**
     * 激活账号
     * @param token
     * @return
     */
    @Override
    public Integer activeAccount(String token) {
        //判断key是否存在
        Object o = redisTemplate.boundValueOps(ShopConstants.ACTIVE_SHOP + token).get();
        if (o==null) throw new MyException("激活码不存在，或已过期");
        Long shopId = (Long) o;
        ShopEntity shopEntity = this.baseMapper.selectById(shopId);
        if (shopEntity==null) throw new MyException("店铺信息不存在");
        if (shopEntity.getState()==ShopEntity.ACTIVATION) throw new MyException("店铺信息已激活");
        //查看店铺是否可以激活
        if (shopEntity.getState()==ShopEntity.APPROVED){
            //激活店铺信息
            shopEntity.setState(ShopEntity.ACTIVATION);
            this.baseMapper.updateById(shopEntity);
            //激活当前店铺的管理端账号
            EmployEntity employEntity = this.employeeMapper.findByShopId(shopId);
            employEntity.setState(1);
            this.employeeMapper.updateById(employEntity);
            //删除redis中的key
            redisTemplate.delete(ShopConstants.ACTIVE_SHOP+token);
            //发送邮件告知用户
            HtmUtils.getActiveSuccessTemplate(employEntity.getUsername(),employEntity.getPassword());
            return 1;
        }
        throw new MyException("店铺审核未通过");
    }

    /**
     *仅限于当用户以审核不通过的状态下进行访问,防止用户的信息被恶意修改
     * @return
     */
    @Override
    @Transactional
    public Integer updateShopMaterial(ShopRegisterDto shopRegisterDto) {
        //查看当前状态
        ShopEntity shop = shopRegisterDto.getShop();

        if (shop.getState()==2) throw new MyException("店铺已经激活");
        //获取该店铺的员工信息
        this.autoAudit(shop);
        shop.setLogo(StringUtils.getFilePath(shop.getLogo(),serverUrl));
        //获得店铺的管理员信息
        EmployEntity employEntity = this.employeeMapper.findByShopId(shop.getId());
        employEntity.setUsername(shopRegisterDto.getUsername());
        employEntity.setPassword(shopRegisterDto.getPassword());
        employEntity.setEmail(shopRegisterDto.getEmail());
        employEntity.setPhone(shopRegisterDto.getPhone());
        this.baseMapper.updateById(shop);
        this.employeeMapper.updateById(employEntity);
        //删除图片信息
        //获取数据中商铺信息
        ShopEntity entity = this.baseMapper.selectById(shop.getId());
        String logs = shop.getLogo();
        //查找出被前端删除的图片
        //数据库中的logo
        List<String> list = Arrays.stream(entity.getLogo().split(",")).collect(Collectors.toList());
        Map<String, String> logosMap = Arrays.stream(logs.split(",")).collect(Collectors.toMap(item -> item, item -> item.toString()));
        for (String s : list) {
            if (!logosMap.containsKey(s)){
                System.out.println(s+"\t要删除的图片");
            }
        }


        return 1;
    }

    /**
     * 调用三分接口自动审核
     * @param shopEntity
     * @return
     */
    @Override
    public boolean autoAudit(ShopEntity shopEntity) {
        //审核店铺名称是否合格
        String text = TextCensor.TextCensor(BaiduAuditUtil.getAuth(), shopEntity.getName());
        TextAuditEntity textAuditEntity = JSON.parseObject(text, TextAuditEntity.class);
        if (!textAuditEntity.getConclusion().equals("合规")){
            if (textAuditEntity.getData()!=null) throw new MyException(textAuditEntity.getData().get(0).getMsg());
            else throw new MyException("店铺名称审核未通过");
        }
        return true;
    }

    /**
     * 根据用户传入的token获取店铺信息和管理员信息
     * @param token
     * @return
     */
    @Override
    public ShopRegisterDto findByToken(String token) {

        BoundValueOperations boundValueOperations = redisTemplate.boundValueOps(ShopConstants.UPDATE_SHOP + token);
        Long shopId = (Long) boundValueOperations.get();
        if (shopId==null)
            return null;
        //查找店铺信息
        ShopEntity shopEntity = this.baseMapper.selectById(shopId);
        //根据店铺id查询管理员信息
        EmployEntity employEntity = this.baseMapper.findByShopIdGetEmployee(shopId);

        ShopRegisterDto shopRegisterDto = new ShopRegisterDto();
        shopRegisterDto.setShop(shopEntity);
        shopRegisterDto.setEmail(employEntity.getEmail());
        shopRegisterDto.setPassword(employEntity.getPassword());
        shopRegisterDto.setUsername(employEntity.getUsername());
        shopRegisterDto.setPhone(employEntity.getPhone());
        //设置文件服务器的访问地址告知前端应该怎么分割地址
        shopRegisterDto.setServerUrl(serverUrl);
        return shopRegisterDto;
    }
}
